package cc.rengu.igas.bsps.core.service.trans;

import cc.rengu.igas.bsps.common.constant.BspsAppParamConstant;
import cc.rengu.igas.bsps.common.dao.BspsMchntAcctInfoMapper;
import cc.rengu.igas.bsps.common.dao.BspsUserInfoMapper;
import cc.rengu.igas.bsps.common.dao.impl.BspsMchntAcctInfoMapperImpl;
import cc.rengu.igas.bsps.common.dao.impl.BspsUserInfoMapperImpl;
import cc.rengu.igas.bsps.common.entity.MchntAcctInfo;
import cc.rengu.igas.bsps.common.entity.UserInfo;
import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.bsps.core.model.UserSessionInfo;
import cc.rengu.igas.bsps.core.service.base.PayService;
import cc.rengu.igas.bsps.facade.request.SettleAcctBalanceQueryRequest;
import cc.rengu.igas.bsps.facade.response.SettleAcctBalanceQueryResponse;
import cc.rengu.igas.share.common.util.SensitiveDataUtil;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.enums.PinTypeEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.PasswordInfo;
import cc.rengu.oltp.service.realize.SafeKeyBoardService;
import cc.rengu.oltp.service.realize.impl.SafeKeyBoardServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.RedisUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import com.alibaba.fastjson.JSON;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 结算账户余额查询.
 */
public class SettleAcctBalanceQueryService extends PayService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        SettleAcctBalanceQueryRequest settleAcctBalanceQueryRequest = new SettleAcctBalanceQueryRequest();
        ConvertUtil.convertOutput(settleAcctBalanceQueryRequest);
        return settleAcctBalanceQueryRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {

        SettleAcctBalanceQueryRequest settleAcctBalanceQueryRequest = (SettleAcctBalanceQueryRequest) request;
        String instId = settleAcctBalanceQueryRequest.getHeader().getInstId();
        String mchntNo = settleAcctBalanceQueryRequest.getMchntNo();
        String transPassword = settleAcctBalanceQueryRequest.getTransPassword();
        String traceNo = settleAcctBalanceQueryRequest.getHeader().getTraceNo();
        String mchntNoAcct = settleAcctBalanceQueryRequest.getSettleAcctNo();
        String sessionId = settleAcctBalanceQueryRequest.getHeader().getSession();
        String sessionObj = RedisUtil.onceGet(sessionId);
        UserSessionInfo userSessionInfo = JSON.parseObject(sessionObj, UserSessionInfo.class);
        if (null == userSessionInfo) {
            rglog.error("session过期");
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        }
        Map<String, String> sensitiveMap = userSessionInfo.getSensitiveMap();
        mchntNoAcct = SensitiveDataUtil.reducition(mchntNoAcct, sensitiveMap);

        List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList();
        if (CollectionUtils.isEmpty(channelCallCfgList)) {
            rglog.error("通道服务调用配置表无数据！,instId:<{}>,traceNo:<{}>,",
                    settleAcctBalanceQueryRequest.getHeader().getInstId(), settleAcctBalanceQueryRequest.getHeader().getTraceNo());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }

        BizResponse<SettleAcctBalanceQueryResponse> bizResponse = new BizResponse<>();
        SettleAcctBalanceQueryResponse settleAcctBalanceQueryResponse = new SettleAcctBalanceQueryResponse();

        BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
        UserInfo userInfo = bspsUserInfoMapper.selectBspsUserInfoByUserId(instId, settleAcctBalanceQueryRequest.getUserId());
        if (userInfo == null) {
            rglog.error("用户不存在", settleAcctBalanceQueryRequest.getUserId(), traceNo);
            throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
        }

        SafeKeyBoardService safeKeyBoardService = new SafeKeyBoardServiceImpl();
        PasswordInfo passwordInfo = new PasswordInfo(mchntNo, PinTypeEnum.DIGITAL, transPassword);
        transPassword = safeKeyBoardService.encryptPassword(instId, null, passwordInfo, null);
        /* step1: 校验交易密码 */
        if (!transPassword.equals(userInfo.getTransPassword())) {
            rglog.error("交易密码校验失败！拒绝提现请求！userId:<{}>，前端流水号：<{}>,transPassword:<{}>", userInfo.getUserId(), traceNo, userInfo.getTransPassword());
            throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
        }

        /* step2: 查询商户结算账户信息 */
        BspsMchntAcctInfoMapper bspsMchntAcctInfoMapper = new BspsMchntAcctInfoMapperImpl();
        List<MchntAcctInfo> mchntAcctInfoList = bspsMchntAcctInfoMapper.selectBspsMchntAcctInfoByMchntNo(instId, mchntNo);
        if (null == mchntAcctInfoList) {
            rglog.error("商户结算账户信息查询失败！拒绝余额请求！userId:<{}>，前端流水号：<{}>,mchntNo:<{}>", userInfo.getUserId(), traceNo, mchntNo);
            throw new BizException(RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespDesc());
        }
        String finalMchntNoAcct = mchntNoAcct;
        Predicate<MchntAcctInfo> acctNo = p -> finalMchntNoAcct.equals(p.getSettleAcctNo());
        Predicate<MchntAcctInfo> status = p -> AppParamConstant.YES.equals(p.getRecordStatus());
        mchntAcctInfoList = mchntAcctInfoList.stream().filter(acctNo.and(status)).collect(Collectors.toList());
        if (null == mchntAcctInfoList) {
            rglog.error("被查询账户<{}>在商户结算账户信息列表查无记录！拒绝余额请求！mchntNo:<{}>", settleAcctBalanceQueryRequest.getSettleAcctNo(), mchntNo);
            throw new BizException(RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespDesc());
        }

        /* TODO 调用esb余额查询 由项目组实现ESB接口 */

        bizResponse.setResult(settleAcctBalanceQueryResponse);
        bizResponse.setRspSysId(AppParamConstant.IGAS);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        SettleAcctBalanceQueryResponse settleAcctBalanceQueryResponse = (SettleAcctBalanceQueryResponse) bizResponse.getResult();
        ConvertUtil.convertInput(settleAcctBalanceQueryResponse);
    }

    String genGlobalTraceNum(String callIndex) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        return BspsAppParamConstant.BSP_SYS_ID + xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + "0" + callIndex;
    }
}
